package com.lanyou.esb.cook.proxy.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections4.map.MultiKeyMap;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import com.lanyou.esb.cook.proxy.common.Constants;
import com.lanyou.esb.cook.proxy.entity.IfAccTimes;

/**
 * 接口访问次数统计持久层
 * 
 * @author Davey.wu
 */
public class IfAccTimesDao extends BaseDao<IfAccTimes> {
	private static final SimpleDateFormat DATEFORMATE_YYYYMMDDHHMMSS = new SimpleDateFormat(
			Constants.DATE_PATTERN_YYYYMMDDHHMMSS);
	private static final List<String> fields = new ArrayList<String>();

	/** SQL **/
	private static final String SQL;

	static {
		fields.add("FIELD_ID");
		fields.add("FIELD_SYSTEM_ID");
		fields.add("IF_ID");
		fields.add("STATISTICS_DATE");
		fields.add("IF_NAME");
		fields.add("ACC_TIME");
		fields.add("IS_ENABLE");
		fields.add("CREATOR");
		fields.add("CREATED_DATE");
		fields.add("MODIFIER");
		fields.add("LAST_UPDATED_DATE");
	}
	static {
		StringBuilder builderFields = new StringBuilder();
		StringBuilder builderValues = new StringBuilder();
		builderFields.append(" (");
		builderValues.append(" (");
		int size = fields.size();
		for (int i = 0; i < size; ++i) {
			builderFields.append(fields.get(i) + (i == size - 1 ? "" : ","));
			builderValues.append((i == size - 1 ? "?" : "?,"));
		}
		builderFields.append(") ");
		builderValues.append(") ");
		SQL = "insert into T_ESB_BU_IF_ACC_TIMES" + builderFields.toString()
				+ "values " + builderValues.toString();
	}

	@Override
	public int save(IfAccTimes ifAccTimes) {
		return getJdbcTemplate().update(SQL, ifAccTimes.getFieldId(),
				ifAccTimes.getSystemId(), ifAccTimes.getIfId(),
				getFormatedDate(ifAccTimes.getStatDate()),
				ifAccTimes.getIfName(), ifAccTimes.getTimes(),
				ifAccTimes.getIsEnable(), ifAccTimes.getCreator(),
				ifAccTimes.getCreateDate(), ifAccTimes.getModifier(),
				ifAccTimes.getLastUpDate());
	}

	@Override
	public int saveAll(List<IfAccTimes> ifAccTimeses) {
		if (ifAccTimeses == null || ifAccTimeses.isEmpty()) {
			return 0;
		}
		MultiKeyMap<String, Boolean> multiKeyMap = find(ifAccTimeses);
		List<IfAccTimes> saves = new ArrayList<>(ifAccTimeses.size());
		List<IfAccTimes> updates = new ArrayList<>(ifAccTimeses.size());
		for (IfAccTimes ifAccTimes : ifAccTimeses) {
			if (multiKeyMap.get(getFormatedDateStr(ifAccTimes.getStatDate()),
					ifAccTimes.getIfId()) != null) {
				updates.add(ifAccTimes);
				continue;
			}
			saves.add(ifAccTimes);
		}

		int result = save(saves);
		result += update(updates);
		return result;
	}

	/**
	 * 查看统计数据是否已经存在
	 * 
	 * @param ifAccTimeses
	 * @return
	 */
	private MultiKeyMap<String, Boolean> find(List<IfAccTimes> ifAccTimeses) {
		// 按日期分组
		Map<String, List<String>> map = new HashMap<>();
		for (IfAccTimes ifAccTimes : ifAccTimeses) {
			String key = getFormatedDateStr(ifAccTimes.getStatDate());
			List<String> list = map.get(key);
			if (list == null) {
				list = new ArrayList<>();
				map.put(key, list);
			}
			list.add(ifAccTimes.getIfId());
		}
		MultiKeyMap<String, Boolean> multiKeyMap = new MultiKeyMap<>();
		for (Entry<String, List<String>> entry : map.entrySet()) {
			List<String> ids = find(entry.getValue(), entry.getKey());
			for (String id : ids) {
				multiKeyMap.put(entry.getKey(), id, true);
			}
		}
		return multiKeyMap;
	}

	/**
	 * 根据日期和接口标识查询统计数据
	 * 
	 * @param value
	 * @param date
	 * @return
	 */
	private List<String> find(List<String> value, String date) {
		String sql = "SELECT DISTINCT t.IF_ID FROM T_ESB_BU_IF_ACC_TIMES t WHERE t.IF_ID in(:ifIds) AND t.STATISTICS_DATE=:statDate";

		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("ifIds", value);
		paramMap.put("statDate", date);
		NamedParameterJdbcTemplate jdbc = new NamedParameterJdbcTemplate(
				this.getJdbcTemplate());
		List<String> result = jdbc.query(sql, paramMap,
				new RowMapper<String>() {

					@Override
					public String mapRow(ResultSet rs, int index)
							throws SQLException {
						return rs.getString("IF_ID");
					}

				});
		return result;
	}

	/**
	 * 保存 接口访问次数统计数据
	 * 
	 * @param ifAccTimeses
	 * @return
	 */
	private int save(List<IfAccTimes> ifAccTimeses) {
		if (ifAccTimeses == null || ifAccTimeses.isEmpty()) {
			return 0;
		}
		List<Object[]> args = new ArrayList<>(ifAccTimeses.size());
		int i = 0;
		for (IfAccTimes ifAccTimes : ifAccTimeses) {
			i = 0;
			Object[] objects = new Object[fields.size()];
			objects[i++] = ifAccTimes.getFieldId();
			objects[i++] = ifAccTimes.getSystemId();
			objects[i++] = ifAccTimes.getIfId();
			objects[i++] = getFormatedDate(ifAccTimes.getStatDate());
			objects[i++] = ifAccTimes.getIfName();
			objects[i++] = ifAccTimes.getTimes();

			objects[i++] = ifAccTimes.getIsEnable();
			objects[i++] = ifAccTimes.getCreator();
			objects[i++] = ifAccTimes.getCreateDate();
			objects[i++] = ifAccTimes.getModifier();
			objects[i++] = ifAccTimes.getLastUpDate();
			args.add(objects);
		}
		int[] results = getJdbcTemplate().batchUpdate(SQL, args);
		if (results == null) {
			return 0;
		}
		int result = 0;
		for (int k : results) {
			result += k;
		}
		return result;
	}

	@Override
	public int update(List<IfAccTimes> list) {
		if (list == null || list.isEmpty()) {
			return 0;
		}
		List<Object[]> args = new ArrayList<>(list.size());
		int i = 0;
		for (IfAccTimes ifAccTimes : list) {
			i = 0;
			Object[] objects = new Object[3];
			objects[i++] = ifAccTimes.getTimes();
			objects[i++] = ifAccTimes.getIfId();
			objects[i++] = getFormatedDateStr(ifAccTimes.getStatDate());
			args.add(objects);
		}
		String sql = "UPDATE  T_ESB_BU_IF_ACC_TIMES SET ACC_TIME=ACC_TIME+? WHERE IF_ID=? AND STATISTICS_DATE=?";
		int[] results = getJdbcTemplate().batchUpdate(sql, args);
		if (results == null) {
			return 0;
		}
		int result = 0;
		for (int k : results) {
			result += k;
		}
		return result;
	}

	/**
	 * 消除时分秒毫秒
	 * 
	 * @param date
	 * @return
	 */
	private Date getFormatedDate(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// 设置日期为每个月的第一天
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	private String getFormatedDateStr(Date date) {
		return DATEFORMATE_YYYYMMDDHHMMSS.format(getFormatedDate(date));
	}
}
